from django.urls import reverse
from utils.bootstrap import BootStrapForm
from django import forms
from django.shortcuts import render, redirect
from django.urls import path
from django.db.models import Q
from django.shortcuts import HttpResponse
from utils.pager import Pagination
from www import models
from django.utils.safestring import mark_safe, SafeData
from utils.encrypt import md5_string
from urllib.parse import quote_plus


class BaseCurd(object):
    list_template_name = 'plus_list.html'

    def __init__(self, view_list, prefix):
        self.view_list = view_list
        self.prefix = prefix

    def displatch(self, func):
        def inner(request, *args, **kwargs):
            # self.request = request
            res = func(request, *args, **kwargs)
            # try:
            #     res = func(request, *args, **kwargs)
            # except Exception as e:
            #     res = HttpResponse("异常")
            return res

        return inner

    @classmethod
    def urls(cls, view_list=None, prefix=None):
        if not view_list:
            view_list = ['list', 'add', 'edit', 'delete']
        if not prefix:
            prefix = cls.__name__.lower()
        instance = cls(view_list, prefix)

        router = []
        for item in view_list:
            func = getattr(instance, item)
            if item in ['list', 'add']:
                router.append(path(f'{item}/', instance.displatch(func), name=f'{prefix}_{item}'))
            else:
                router.append(path(f'{item}/<int:pk>/', instance.displatch(func), name=f'{prefix}_{item}'))

        extra_router = instance.get_extra_url()
        if extra_router:
            router.extend(extra_router)
        return (router, None, None)

    def get_extra_url(self):
        return None

    def get_queryset(self, request):
        return self.queryset

    def list(self, request):
        queryset = self.get_queryset(request)
        pager = Pagination(request, queryset)
        context = {
            'pager': pager,
            'table_header': self.table_header,
            'table_field': self.table_field,
            'url_add_name': f"{self.prefix}_add",
            'url_edit_name': f"{self.prefix}_edit",
            'url_delete_name': f"{self.prefix}_delete"
        }
        return render(request, self.list_template_name, context)

    def add(self, request):
        form_class = self.form_class
        origin = request.GET.get('redirect')
        if request.method == 'GET':
            form = form_class()
            return render(request, 'form2.html', {'form': form})
        form = form_class(data=request.POST)
        if not form.is_valid():
            return render(request, 'form2.html', {'form': form})
        form.save()
        return redirect(origin)

    def edit(self, request, pk):
        form_class = self.form_class
        origin = request.GET.get('redirect')
        instance = self.get_instance(request, pk)
        if request.method == 'GET':
            form = form_class(instance=instance)
            return render(request, 'form2.html', {'form': form})
        form = form_class(data=request.POST, instance=instance)
        if not form.is_valid():
            return render(request, 'form2.html', {'form': form})
        form.save()
        return redirect(origin)

    def get_instance(self, request, pk):
        return None

    def delete(self, request, pk):
        origin = request.GET.get('redirect')
        if request.method == 'GET':
            return render(request, 'delete.html', {"origin": origin})
        self.do_delete(request, pk)
        return redirect(origin)

    def do_delete(self, request, pk):
        pass


class PriceModelForm(BootStrapForm, forms.ModelForm):
    class Meta:
        model = models.PricePolicy
        fields = ['count', 'price']


class Price3(BaseCurd):
    queryset = models.PricePolicy.objects.all().order_by('count')
    form_class = PriceModelForm
    table_header = ['数量', '价格']
    table_field = ['count', 'price']

    def get_instance(self, request, pk):
        return models.PricePolicy.objects.filter(id=pk).first()

    def do_delete(self, request, pk):
        models.PricePolicy.objects.filter(id=pk).delete()

    # def get_extra_url(self):
    #     return [path(f'export/', self.export, name=f'price3_export')]
    #
    # def export(self, request):
    #     return HttpResponse('export')

    # def list(self, request):
    #     return HttpResponse("price list")


class LevelModelForm(BootStrapForm, forms.ModelForm):
    class Meta:
        model = models.Level
        fields = ['title', 'percent']


class Level3(BaseCurd):
    queryset = models.Level.objects.filter(active=1).order_by('percent')
    form_class = LevelModelForm
    table_header = ['标题', '折扣（百分比）']
    table_field = ['title', 'percent']

    def get_instance(self, request, pk):
        return models.Level.objects.filter(id=pk).first()

    def do_delete(self, request, pk):
        models.Level.objects.filter(id=pk, active=1).update(active=0)


class BaseCurd4(object):
    list_template_name = 'v4_list.html'
    add_template = 'form2.html'
    edit_template = 'form2.html'
    search_field_list = []

    def __init__(self, view_list, prefix):
        self.view_list = view_list
        self.prefix = prefix

    def dispatch(self, func):
        def inner(request, *args, **kwargs):
            self.request = request
            res = func(request, *args, **kwargs)
            # try:
            #     res = func(request, *args, **kwargs)
            # except Exception as e:
            #     res = HttpResponse("异常")
            return res

        return inner

    @classmethod
    def urls(cls, view_list=None, prefix=None):
        if not view_list:
            view_list = ['list', 'add', 'edit', 'delete']
        if not prefix:
            prefix = cls.__name__.lower()
        instance = cls(view_list, prefix)

        router = []
        for item in view_list:
            func = getattr(instance, item)
            if item in ['list', 'add']:
                router.append(path(f'{item}/', instance.dispatch(func), name=f'{prefix}_{item}'))
            else:
                router.append(path(f'{item}/<int:pk>/', instance.dispatch(func), name=f'{prefix}_{item}'))

        extra_router = instance.get_extra_url()
        if extra_router:
            router.extend(extra_router)
        return (router, None, None)

    def get_extra_url(self):
        return None

    def get_queryset(self, request):
        return self.queryset

    def list(self, request):
        queryset = self.get_queryset(request)
        keyword = request.GET.get('keyword', "").strip()
        if self.search_field_list:
            con = Q()
            if keyword:
                con.connector = 'OR'
                for search_field in self.search_field_list:
                    con.children.append((search_field, keyword))
                queryset = queryset.filter(con)
        pager = Pagination(request, queryset)
        context = {
            'pager': pager,
            'table_header': self.table_header,
            'table_field': self.table_field,
            'url_add_name': f"{self.prefix}_add",
            'url_edit_name': f"{self.prefix}_edit",
            'url_delete_name': f"{self.prefix}_delete",
            'search_field_list': self.search_field_list,
            'keyword': keyword
        }
        return render(request, self.list_template_name, context)

    def add(self, request):
        form_class = self.add_form_class
        origin = request.GET.get('redirect')
        if request.method == 'GET':
            form = form_class()
            return render(request, self.add_template, {'form': form})
        form = form_class(data=request.POST)
        if not form.is_valid():
            return render(request, self.add_template, {'form': form})

        self.add_save(form)

        return redirect(origin)

    def add_save(self, form):
        form.save()

    def edit(self, request, pk):
        form_class = self.edit_form_class
        origin = request.GET.get('redirect')
        instance = self.get_instance(request, pk)
        if request.method == 'GET':
            form = form_class(instance=instance)
            return render(request, self.edit_template, {'form': form})
        form = form_class(data=request.POST, instance=instance)
        if not form.is_valid():
            return render(request, self.edit_template, {'form': form})
        self.edit_save(form)

        return redirect(origin)

    def edit_save(self, form):
        form.save()

    def get_instance(self, request, pk):
        return None

    def delete(self, request, pk):
        origin = request.GET.get('redirect')
        if request.method == 'GET':
            return render(request, 'delete.html', {"origin": origin})
        self.do_delete(request, pk)
        return redirect(origin)

    def do_delete(self, request, pk):
        pass


class Price4ModelForm(BootStrapForm, forms.ModelForm):
    class Meta:
        model = models.PricePolicy
        fields = ['count', 'price']


class Price4(BaseCurd4):
    queryset = models.Level.objects.filter(active=1).order_by('percent')
    add_form_class = Price4ModelForm
    edit_form_class = Price4ModelForm
    search_field_list = ['title__contains']

    def more(instance):
        # print(instance)
        return mark_safe(f"<a href='#'>测试{instance.id}--{instance.title}</a>")

    table_header = ['标题', '折扣（百分比）']
    table_field = [('field', 'title'), ('field', 'percent'), ('func', more)]

    def get_instance(self, request, pk):
        return models.Level.objects.filter(id=pk).first()

    def do_delete(self, request, pk):
        models.Level.objects.filter(id=pk, active=1).update(active=0)


class Level4(BaseCurd):
    queryset = models.Level.objects.filter(active=1).order_by('percent')
    add_form_class = Price4ModelForm
    edit_form_class = Price4ModelForm
    table_header = ['标题', '折扣（百分比）']
    table_field = [('field', 'title'), ('field', 'percent')]

    def get_instance(self, request, pk):
        return models.Level.objects.filter(id=pk).first()

    def do_delete(self, request, pk):
        models.Level.objects.filter(id=pk, active=1).update(active=0)


class CustomerModelForm(BootStrapForm, forms.ModelForm):
    exclude_field_list = ['level']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['level'].queryset = models.Level.objects.filter(active=1)

    password = forms.CharField(widget=forms.PasswordInput(render_value=True), label='密码')
    password_repeat = forms.CharField(widget=forms.PasswordInput(render_value=True), label='确认密码')

    class Meta:
        model = models.Customer
        fields = ['level', 'username', 'mobile', 'password', 'password_repeat']
        widgets = {
            'level': forms.RadioSelect(attrs={'class': 'form-radio'}),  # 设置 level 字段的默认组件类型,
        }

    def clean_password(self):
        password = self.cleaned_data['password']
        md5_pwd = md5_string(password)
        return md5_pwd

    def clean_password_repeat(self):
        password = self.cleaned_data['password']
        password_repeat = md5_string(self.cleaned_data['password_repeat'])
        if password != password_repeat:
            raise forms.ValidationError('密码不一致')
        md5_pwd_repeat = md5_string(password_repeat)
        return md5_pwd_repeat


class CustomerEditModelForm(BootStrapForm, forms.ModelForm):
    exclude_field_list = ['level']

    class Meta:
        model = models.Customer
        fields = ['level', 'username', 'mobile']
        widgets = {
            'level': forms.RadioSelect(attrs={'class': 'form-radio'})
        }


class CustomerResetModelForm(BootStrapForm, forms.ModelForm):
    password_repeat = forms.CharField(widget=forms.PasswordInput(render_value=True), label='确认密码', required=False)
    password = forms.CharField(widget=forms.PasswordInput(render_value=True), label='密码', required=False)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 隐藏密码和确认密码字段
        self.initial['password'] = ''

    def clean_password(self):
        password = md5_string(self.cleaned_data['password'])
        return password

    def clean_password_repeat(self):
        password_repeat = md5_string(self.cleaned_data['password_repeat'])
        password = self.cleaned_data['password']
        if password != password_repeat:
            raise forms.ValidationError('两次密码不一致')
        return password_repeat

    class Meta:
        model = models.Customer
        fields = ['username', 'password', 'password_repeat']
        widgets = {
            'username': forms.TextInput(attrs={'readonly': True})  # 设置用户名为只读
        }

class Customer4(BaseCurd4):
    queryset = models.Customer.objects.filter(active=1).order_by('-id')
    add_form_class = CustomerModelForm
    edit_form_class = CustomerEditModelForm
    add_template = 'form.html'
    edit_template = 'form.html'

    search_field_list = ['username','mobile__contains']
    table_header = ['用户名', '手机号', '级别', '创建日期', '重置密码']

    def get_instance(self, request, pk):
        return models.Customer.objects.filter(id=pk, active=1).first()

    def add_save(self, form):
        form.instance.creator_id = self.request.nb_user.id
        form.save()

    def get_level(request, instance):
        return f"{instance.level.title}（{instance.level.percent}%折扣）"

    def get_create_date(request, instance):
        return instance.create_date.strftime('%Y-%m-%d')

    def reset_password(request, instance):
        url = reverse(viewname=f"customer4_reset", kwargs={'pk': instance.id})
        current_url = request.get_full_path()
        param = quote_plus(current_url)
        return mark_safe(f"<a href='{url}?redirect={param}'>重置密码</>")

    table_field = [('field', 'username'), ('field', 'mobile'), ('func', get_level), ('func', get_create_date),
                   ('func', reset_password)]

    def do_delete(self, request, pk):
        models.Customer.objects.filter(id=pk, active=1).update(active=0)

    def get_extra_url(self):
        return [
            path(f'reset/<int:pk>/', self.dispatch(self.reset), name=f"{self.prefix}_reset")
        ]

    def reset(self, request, pk):
        origin = request.GET.get('redirect', '/home/')
        instance = models.Customer.objects.filter(id=pk).first()
        # initial_data = {'username': instance.username}
        if request.method == 'GET':
            form = CustomerResetModelForm(instance=instance)
            return render(request, 'form.html', {"form": form})
        form = CustomerResetModelForm(data=request.POST, instance=instance)
        if not form.is_valid():
            return render(request, 'form.html', {'form': form})
        form.save()
        return redirect(origin)
